import sys
import os
import tempfile
import subprocess # subprocess is generally fine for single process calls, but QProcess is more PySide-native.
from PySide6.QtWidgets import (
    QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
    QPushButton, QListWidget, QListWidgetItem, QLineEdit,
    QLabel, QFileDialog, QMessageBox, QFrame,
    QSizePolicy # For flexible sizing
)
from PySide6.QtCore import Qt, QUrl, QProcess, Slot # Import QProcess and Slot
from PySide6.QtGui import QFont, QColor, QPalette, QIcon # Added QIcon


class FFmpegMergeTool(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("FFmpeg 视频合并工具 (内存优化版) 🎞️")
        self.setGeometry(300, 300, 800, 600) # Increased default size for better layout

        # 设置窗口图标
        # 如果您有自定义图标文件（.ico），可以将其放置在与脚本相同的目录下，并取消下一行的注释
        # self.setWindowIcon(QIcon("your_icon.ico"))

        # --- 深色模式配色方案 ---
        palette = self.palette()
        palette.setColor(QPalette.Window, QColor("#282c34"))
        palette.setColor(QPalette.WindowText, QColor("#ecf0f1"))
        palette.setColor(QPalette.Base, QColor("#3c4048"))
        palette.setColor(QPalette.Text, QColor("#ecf0f1"))
        palette.setColor(QPalette.Button, QColor("#61afef"))
        palette.setColor(QPalette.ButtonText, QColor("#282c34"))
        palette.setColor(QPalette.Highlight, QColor("#61afef"))
        palette.setColor(QPalette.HighlightedText, QColor("#282c34"))
        self.setPalette(palette)

        # 设置主窗口部件
        main_widget = QWidget()
        self.setCentralWidget(main_widget)
        main_layout = QVBoxLayout(main_widget)
        main_layout.setContentsMargins(20, 20, 20, 20)
        main_layout.setSpacing(15)

        # 设置字体
        font = QFont("Segoe UI", 10)
        self.setFont(font)

        # --- 文件列表区域 ---
        self.file_list_widget = QListWidget()
        self.file_list_widget.setDragDropMode(QListWidget.InternalMove) # 允许拖拽重新排序
        self.file_list_widget.setSelectionMode(QListWidget.ExtendedSelection) # 允许多选
        self.file_list_widget.setStyleSheet("""
            QListWidget {
                background-color: #3c4048;
                border: 1px solid #4e535e;
                border-radius: 8px;
                color: #ecf0f1;
                padding: 5px;
                font-size: 13px;
                selection-background-color: #61afef;
                selection-color: #282c34;
            }
            QListWidget::item {
                padding: 4px;
            }
            QListWidget::item:hover {
                background-color: #4e535e; /* Hover effect */
            }
        """)
        # 设置策略，使其能够扩展
        self.file_list_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        main_layout.addWidget(self.file_list_widget)

        # --- 文件操作按钮区域 ---
        file_buttons_layout = QHBoxLayout()
        # 按钮样式统一
        button_style = """
            QPushButton {
                background-color: #61afef;
                color: #282c34;
                border: none;
                border-radius: 8px;
                font-weight: bold;
                font-size: 13px;
                padding: 8px 15px;
            }
            QPushButton:hover {
                background-color: #559edc;
            }
            QPushButton:pressed {
                background-color: #4a8bcc;
            }
        """

        self.add_file_btn = QPushButton("添加文件")
        self.add_file_btn.clicked.connect(self.add_files)
        self.add_file_btn.setStyleSheet(button_style)
        file_buttons_layout.addWidget(self.add_file_btn)

        self.remove_selected_btn = QPushButton("移除选中")
        self.remove_selected_btn.clicked.connect(self.remove_selected_files)
        self.remove_selected_btn.setStyleSheet(button_style)
        file_buttons_layout.addWidget(self.remove_selected_btn)

        self.clear_list_btn = QPushButton("清空列表")
        self.clear_list_btn.clicked.connect(self.clear_file_list)
        self.clear_list_btn.setStyleSheet(button_style)
        file_buttons_layout.addWidget(self.clear_list_btn)

        main_layout.addLayout(file_buttons_layout)

        # --- 输出路径区域 ---
        output_path_frame = QFrame()
        output_path_frame.setFrameShape(QFrame.StyledPanel)
        output_path_frame.setFrameShadow(QFrame.Raised)
        output_path_frame.setStyleSheet("""
            QFrame {
                background-color: #3c4048;
                border: 1px solid #4e535e;
                border-radius: 10px;
                padding: 10px;
            }
        """)
        output_layout = QHBoxLayout(output_path_frame)
        output_layout.setContentsMargins(5, 5, 5, 5) # Smaller margins inside frame

        self.output_label = QLabel("输出路径:")
        self.output_label.setStyleSheet("color: #ecf0f1; font-size: 13px;")
        output_layout.addWidget(self.output_label)

        self.output_path_input = QLineEdit()
        self.output_path_input.setPlaceholderText("请选择输出文件路径...")
        self.output_path_input.setReadOnly(True) # 用户不能直接编辑，只能通过按钮选择
        self.output_path_input.setFixedHeight(35)
        self.output_path_input.setStyleSheet("""
            QLineEdit {
                padding: 8px;
                border: 1px solid #4e535e;
                border-radius: 6px;
                font-size: 13px;
                color: #ecf0f1;
                background-color: #282c34;
            }
        """)
        output_layout.addWidget(self.output_path_input)

        self.select_output_btn = QPushButton("选择输出文件...")
        self.select_output_btn.clicked.connect(self.select_output_file)
        self.select_output_btn.setStyleSheet(button_style.replace("#61afef", "#28a745").replace("#559edc", "#218838").replace("#4a8bcc", "#1e7e34")) # Green button
        output_layout.addWidget(self.select_output_btn)

        main_layout.addWidget(output_path_frame)

        # --- 开始合并按钮 ---
        self.start_merge_btn = QPushButton("开始合并")
        self.start_merge_btn.clicked.connect(self.start_merging)
        self.start_merge_btn.setFixedHeight(50) # Make it larger and prominent
        self.start_merge_btn.setStyleSheet(button_style.replace("padding: 8px 15px", "padding: 10px 20px").replace("font-size: 13px", "font-size: 16px"))
        main_layout.addWidget(self.start_merge_btn)

        # --- 状态标签 ---
        self.status_label = QLabel("就绪")
        self.status_label.setAlignment(Qt.AlignCenter)
        self.status_label.setStyleSheet("color: #99aab5; font-size: 12px;")
        main_layout.addWidget(self.status_label)

        # FFmpeg 进程对象
        self.process = QProcess(self)
        self.process.readyReadStandardOutput.connect(self.handle_stdout)
        self.process.readyReadStandardError.connect(self.handle_stderr)
        self.process.finished.connect(self.process_finished)
        self.process.errorOccurred.connect(self.process_error)

    @Slot()
    def add_files(self):
        # 允许选择多个视频文件
        file_paths, _ = QFileDialog.getOpenFileNames(
            self, "选择视频文件", "",
            "视频文件 (*.mp4 *.mov *.avi *.mkv *.flv *.webm);;所有文件 (*)"
        )
        for path in file_paths:
            if path and not self.file_list_widget.findItems(path, Qt.MatchExactly): # 避免重复添加
                self.file_list_widget.addItem(path)
        self.status_label.setText(f"已添加 {len(file_paths)} 个文件。当前列表有 {self.file_list_widget.count()} 个文件。")

    @Slot()
    def remove_selected_files(self):
        # 从后往前删除，避免索引变化问题
        for item in reversed(self.file_list_widget.selectedItems()):
            row = self.file_list_widget.row(item)
            self.file_list_widget.takeItem(row)
        self.status_label.setText(f"已移除选中文件。当前列表有 {self.file_list_widget.count()} 个文件。")

    @Slot()
    def clear_file_list(self):
        self.file_list_widget.clear()
        self.status_label.setText("文件列表已清空。")

    @Slot()
    def select_output_file(self):
        # 允许用户选择输出文件的保存位置和名称
        output_path, _ = QFileDialog.getSaveFileName(
            self, "选择输出视频文件", "merged_video.mp4",
            "MP4 视频 (*.mp4);;MOV 视频 (*.mov);;AVI 视频 (*.avi);;所有文件 (*)"
        )
        if output_path:
            self.output_path_input.setText(output_path)
            self.status_label.setText(f"输出路径已设定: {os.path.basename(output_path)}")

    @Slot()
    def start_merging(self):
        input_files = [self.file_list_widget.item(i).text() for i in range(self.file_list_widget.count())]
        output_file = self.output_path_input.text().strip()

        if not input_files:
            QMessageBox.warning(self, "错误", "请先添加要合并的视频文件！")
            self.status_label.setText("合并失败: 未添加文件 🚫")
            return

        if len(input_files) < 2:
            QMessageBox.warning(self, "错误", "请至少添加两个视频文件进行合并！")
            self.status_label.setText("合并失败: 文件数量不足 🚫")
            return

        if not output_file:
            QMessageBox.warning(self, "错误", "请选择一个输出文件路径！")
            self.status_label.setText("合并失败: 未指定输出路径 🚫")
            return

        if self.process.state() == QProcess.Running:
            QMessageBox.information(self, "提示", "FFmpeg 正在运行中，请等待当前操作完成。")
            return

              # 创建一个临时文件来列出所有输入视频
        try:
            # 使用 tempfile 确保临时文件创建和删除的安全性
            with tempfile.NamedTemporaryFile(mode='w', delete=False, encoding='utf-8') as f:
                self.temp_list_file = f.name # 保存临时文件路径以便后续删除
                for filepath in input_files:
                    escaped_filepath = filepath.replace("'", r"\'")
                    f.write(f"file '{escaped_filepath}'\n")
        except Exception as e:
            QMessageBox.critical(self, "错误", f"创建临时文件失败: {e}")
            self.status_label.setText("合并失败: 无法创建临时列表文件 ❌")
            return

        # FFmpeg 命令：使用 concat demuxer 和 -c copy 进行快速合并
        # -safe 0 允许文件列表中的绝对路径
        command = [
            "ffmpeg",
            "-f", "concat",
            "-safe", "0",
            "-i", self.temp_list_file,
            "-c", "copy",
            output_file
        ]

        self.status_label.setText("开始合并视频... 请等待 ⏳")
        self.start_merge_btn.setEnabled(False) # 禁用按钮避免重复点击
        self.process.start(command[0], command[1:]) # command[0] is 'ffmpeg', rest are arguments

    @Slot()
    def handle_stdout(self):
        data = self.process.readAllStandardOutput().data().decode(sys.stdout.encoding or 'utf-8', errors='ignore')
        # 可以将这些输出显示在日志框中，这里简化为只在状态栏更新
        # print("FFmpeg STDOUT:", data) # For debugging

    @Slot()
    def handle_stderr(self):
        # FFmpeg 的进度和错误信息通常输出到 stderr
        data = self.process.readAllStandardError().data().decode(sys.stderr.encoding or 'utf-8', errors='ignore')
        # 简单显示最后一行信息，可以考虑解析进度信息
        lines = data.strip().split('\n')
        if lines:
            self.status_label.setText(f"FFmpeg 输出: {lines[-1]} 🛠️")
        # print("FFmpeg STDERR:", data) # For debugging

    @Slot(int, QProcess.ExitStatus)
    def process_finished(self, exit_code, exit_status):
        self.start_merge_btn.setEnabled(True) # 重新启用按钮

        # 清理临时文件
        if hasattr(self, 'temp_list_file') and os.path.exists(self.temp_list_file):
            try:
                os.remove(self.temp_list_file)
                # print(f"Temporary file {self.temp_list_file} cleaned.")
            except Exception as e:
                print(f"Error cleaning temporary file {self.temp_list_file}: {e}")

        if exit_status == QProcess.NormalExit and exit_code == 0:
            self.status_label.setText(f"视频合并成功！输出文件: {self.output_path_input.text()} 🎉")
            QMessageBox.information(self, "成功", "视频已成功合并！")
        else:
            error_message = self.process.readAllStandardError().data().decode(sys.stderr.encoding or 'utf-8', errors='ignore')
            self.status_label.setText(f"视频合并失败 (错误码: {exit_code}) ❌")
            QMessageBox.critical(self, "合并失败", f"FFmpeg 合并操作失败。\n错误信息:\n{error_message}")

    @Slot(QProcess.ProcessError)
    def process_error(self, error):
        self.start_merge_btn.setEnabled(True)
        error_msg = ""
        if error == QProcess.FailedToStart:
            error_msg = "FFmpeg 程序未找到。请确保 FFmpeg 已安装并添加到系统 PATH 或放在程序同目录下。"
        elif error == QProcess.Crashed:
            error_msg = "FFmpeg 进程崩溃。"
        else:
            error_msg = f"FFmpeg 进程发生未知错误: {error}"
        self.status_label.setText(f"合并失败: {error_msg} ❗")
        QMessageBox.critical(self, "FFmpeg 错误", error_msg)


if __name__ == "__main__":
    # 启用高清DPI缩放，确保界面在高分辨率屏幕上正常显示
    QApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
    QApplication.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)

    app = QApplication(sys.argv)
    window = FFmpegMergeTool()
    window.show()
    sys.exit(app.exec())